#!/usr/bin/perl -w
# Bug reports and comments to Igor.Ermolaev@intel.com
use strict;
no warnings "portable";

use constant { FALSE=>0, TRUE=>-1 };

my @lines    = ();
my $file     = undef;
my $line     = undef;
my $limit    = 0;
my $src_rqrd = TRUE;

if( $#ARGV >= 0 && $ARGV[0] eq '-a' )
{
   $src_rqrd = FALSE;
   shift;
}

my @blocks = ();
for(@ARGV)
{
   if( /^(\d+)(\:(\d+))?/o ){ push @blocks, { addr=>$1, size=>$3 }; }
   else                     { print $_, "\n"; }
}

if( $src_rqrd == FALSE && !@blocks )
{
   print "-a\n" if $src_rqrd == FALSE;
}
elsif( !@ARGV || @blocks )
{
   if( $src_rqrd == FALSE )
   {
      $file = '';
      $line = 0;
   }
   my $sep_cnt = 0;
   while( <STDIN> ) 
   { 
      if( /^\s*([^:]+)\:(\d+)\s*$/o )
      {
         $file  = $1;
         $line  = $2;
         $limit = 0;
         push @lines, { file=>$file, line=>$line, sign=>0, idx=>0 } if !@blocks && $sep_cnt & 1 && ( $#lines < 0 || $lines[$#lines]{file} ne $file || $lines[$#lines]{line} != $line );
      }
      elsif( /^;---/o )
      {
         $sep_cnt++;
      }
      elsif( defined $line && /^\s*(0x)?([[:xdigit:]]+)\s*\:\s+(.+)$/o )
      {
         my $cur    = hex $2;
         my $iline  = $3;
         my $inside = FALSE;
         for(@blocks)
         {
            if(  defined $_->{size} && $cur >= $_->{addr} && $cur < $_->{addr}+$_->{size} ||
                !defined $_->{size} && $cur == $_->{addr} )
            {
               push @lines, { file=>$file, line=>$line, sign=>0, idx=>0 } if $#lines < 0 || $lines[$#lines]{file} ne $file || $lines[$#lines]{line} != $line;
               $inside = TRUE;
               last;
            }
         }
         if( $#lines >= 0 && ( @blocks && $inside == TRUE || !@blocks && $sep_cnt&1 ) )
         {
            if   ( $iline =~ /^\w+blend\w+/io   ){ $lines[$#lines]{sign}-= 4; }
            elsif( $iline =~ /^\w+f(n)?m[as]/io ){ $lines[$#lines]{sign}-= 3; }
            elsif( $iline =~ /^\w+vmul/io       ){ $lines[$#lines]{sign}-= 2; }
            elsif( $iline =~ /^\w+v(add|sub)/io ){ $lines[$#lines]{sign}-= 1; }
            elsif( $iline =~ /^\w+mov/io        ){ $lines[$#lines]{sign}+= 0; }
            elsif( $iline =~ /^\w+cmp|j\w+/io   ){ $lines[$#lines]{sign}+= 1; }
            elsif( $iline =~ /^call\w+/io       ){ $lines[$#lines]{sign}+= 5; }
            else                                 { $lines[$#lines]{sign}+= 2; }
         }
      }
      if( ++$limit == 500 )
      {
         if( $src_rqrd == TRUE ){ $line = undef; }
         else
         {
            $file = '';
            $line = 0;
         }
      }
   }

   my @sorted = sort { ( $a->{file} cmp $b->{file} ) || ( $a->{line} <=> $b->{line} ) } @lines;
   for( my $i = $#sorted - 1; $i >= 0; $i-- )
   {
      if( $sorted[$i]{file} eq $sorted[$i+1]{file} && $sorted[$i]{line} == $sorted[$i+1]{line} )
      {
         $sorted[$i+1]{sign}+= $sorted[$i]{sign};
         splice @sorted, $i, 1;
      }
   }

   if( $#sorted >= 0 )
   {
      my @f = shift @sorted;
      for(0..$#sorted){ $sorted[$_]->{idx} = $_; }
      my $mid = ( $#sorted + 1 ) >> 1;
      @sorted = sort { ( $b->{sign} <=> $a->{sign} ) || ( abs( $a->{idx} - $mid ) <=> abs( $b->{idx} - $mid ) ) } @sorted;
      push @sorted, @f;
      for(@sorted){ print( $file ne '' && $line > 0 ? "$_->{file}:$_->{line}\n" : "-a\n" ); }
   }

   if( 0 )
   {
      for( my $i = 1; $i <= $#sorted + 1; $i++ )
      {
         my $j = ( $#sorted + 1 ) >> 1;
         if( $i & 1 ){ $j += $i >> 1; }
         else        { $j -= $i >> 1; }
         print "$sorted[$j]{file}:$sorted[$j]{line}\n";
      }
   }
}
